/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
 * (c) 2001 - 2013 OpenPlans
 * This code is licensed under the GPL 2.0 license, available at the root
 * application directory.
 */
package org.geoserver.wicket.test;

import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.WicketServlet;
import org.apache.wicket.resource.Properties;
import org.apache.wicket.resource.PropertiesFactory;
import org.apache.wicket.resource.loader.ClassStringResourceLoader;
import org.apache.wicket.resource.loader.ComponentStringResourceLoader;
import org.apache.wicket.settings.ResourceSettings;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.webapp.WebAppContext;
import org.geoserver.web.GeoServerApplication;
import org.geoserver.web.GeoServerResourceStreamLocator;
import org.geoserver.web.GeoServerStringResourceLoader;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHolder;

/**
 * Application object for your web application.
 */
public class WicketTestApplication extends WebApplication
{    
    /**
     * Constructor
     */
	public WicketTestApplication()
	{
	}
	
        static String wtapath = WicketTestApplication.class.getPackage().getName().replaceAll( "\\.", "/");
        static String gsapath = GeoServerApplication.class.getPackage().getName().replaceAll( "\\.", "/");
        static {
            wtapath += "/" + WicketTestApplication.class.getSimpleName();
            gsapath += "/" + GeoServerApplication.class.getSimpleName();
        }

        @Override
        protected void init() {
            //JD: override some resource settings to allow for custom i18n lookups
            getResourceSettings().setResourceStreamLocator(new GeoServerResourceStreamLocator());
            
            getResourceSettings().getStringResourceLoaders().add(new GeoServerStringResourceLoader());
            getResourceSettings().getStringResourceLoaders().add(new ComponentStringResourceLoader());
            getResourceSettings().getStringResourceLoaders().add(new ClassStringResourceLoader(this.getClass()));

            getResourceSettings().setPropertiesFactory(new PropertiesFactory(new ResourceSettings(this)) {
                @Override
                public Properties load(Class<?> clazz, String path) {
                    if ( clazz == WicketTestApplication.class && path.startsWith(wtapath)) {
                        String newPath = path.replace( wtapath, gsapath );
                        return super.load( GeoServerApplication.class, newPath );
                    }
                    return super.load(clazz, path);
                }
            });
        }
        
        /**
	 * @see wicket.Application#getHomePage()
	 */
        
	public Class<? extends Page> getHomePage()
	{
		return TestHomePage.class;
	}

	/**
	 * <p>Starts a Wicket tester application that will allow for quick interactive testing
	 * of the {@link Component} generated by the factory (may be a {@link Page}, in that case the
	 * home page will redirect to it).</p>
	 * <p>The application will be hosted on path "/", port 8080</p>
	 * @param factory
	 */
	public static void start(IComponentFactory factory) {
	    start(factory, "/", 8080);
	}
	
	/**
	 * Same as {@link #start(IComponentFactory)}, but allows to specify the context path and the
	 * port 
	 * @param factory
	 * @param contextPath
	 * @param port
	 */
	public static void start(IComponentFactory factory, String contextPath, int port)  {
	    // sanity check and install the factory
	    if(factory == null) {
	        throw new NullPointerException("You must provide a non null component factory");
	    }
	    TestHomePage.componentFactory = factory;
	    
	    // setup the embedded Jetty server
        Server server = new Server();
        ServerConnector connector = new ServerConnector(server);
        
        // Set some timeout options to make debugging easier.
        connector.setIdleTimeout(1000 * 60 * 60);
        connector.setSoLingerTime(-1);
        connector.setPort(port);
        server.setConnectors(new Connector[] { connector });

        // programmatically add the wicket servlet to the context
        ServletContextHandler root = new ServletContextHandler(server, contextPath, WebAppContext.SESSIONS);
        ServletHolder wicket = new ServletHolder(WicketServlet.class);
        wicket.setInitParameter("applicationClassName", WicketTestApplication.class.getName());
        root.addServlet(wicket, "/*");

        try {
            System.out.println(">>> STARTING EMBEDDED JETTY SERVER, PRESS ANY KEY TO STOP");
            server.start();
            while (System.in.available() == 0) {
                Thread.sleep(1000);
            }
            server.stop();
            server.join();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(100);
        }
    }
}
